from datetime import datetime
from app import db
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
from hashlib import md5

'''
这个文件是指行为，指用户操作之后后台进行的部分操作
'''

# 关注者数据辅助表
followers = db.Table('followers',
                     db.Column('follower_id', db.Integer, db.ForeignKey('user.id')),
                     db.Column('followed_id', db.Integer, db.ForeignKey('user.id'))
                     )

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password = db.Column(db.String(128))
    password_hash = db.Column(db.String(128))
    about_me = db.Column(db.String(140))
    last_seen = db.Column(db.DateTime, default=datetime.utcnow)
    posts = db.relationship('Post', backref='author', lazy='dynamic')

    def __repr__(self):
        return '<User {}>'.format(self.username)

    #设置密码
    def set_password(self, password):
        self.password_hash = generate_password_hash(password)
        # self.password=password

    #检查密码
    def check_password(self, password):
        return check_password_hash(self.password_hash, password)
        # return self.password == password

    #头像
    def avatar(self, size):
        digest = md5(self.email.lower().encode('utf-8')).hexdigest()
        return 'https://www.gravatar.com/avatar/{}?d=identicon&s={}'.format(digest, size)

    #关注者数据辅助表
    followed = db.relationship(
        'User', secondary=followers,                                        # User：生成两个User表。secondary用来指明辅助表
        primaryjoin=(followers.c.follower_id == id),                        # 表示表一（发起关注）与辅助表连接的条件
        secondaryjoin=(followers.c.followed_id == id),                      # 表示表二（被关注者）与辅助表连接的条件
        backref=db.backref('followers', lazy='dynamic'), lazy='dynamic')
        # 定义了如何从右边用户访问这个关系，当我们做出一个名为 followed 的查询的时候，
        # 将会返回所有跟左边用户联系的右边的用户。当我们做出一个名为 followers 的查询的时候，
        # 将会返回一个所有跟右边联系的左边的用户。简单来说就是打开粉丝列表（followed），
        # 可以看到里面有多少粉丝（关注自己的人），打开关注列表（follow），可以看到里面有多少我关注的人。

    # 关注
    def follow(self, user):
        if not self.is_following(user):
            self.followed.append(user)

    # 取消关注
    def unfollow(self, user):
        if self.is_following(user):
            self.followed.remove(user)

    # 正在关注
    def is_following(self, user):
        return self.followed.filter(
            followers.c.followed_id == user.id).count() > 0

    # 关注的帖子
    def followed_posts(self):
        followed = Post.query.join(
            followers, (followers.c.followed_id == Post.user_id)).filter(
                followers.c.follower_id == self.id)
        own = Post.query.filter_by(user_id=self.id)
        return followed.union(own).order_by(Post.timestamp.desc())

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.String(140))
    timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    # author = db.Column()
    def __repr__(self):
        return '<Post {}>'.format(self.body)
